package com.simafei.flow.core;

import com.simafei.flow.core.api.Api;
import com.simafei.flow.core.api.ApiNode;
import com.simafei.flow.core.api.impl.ApiExecutor;
import com.simafei.flow.core.common.NodeType;
import com.simafei.flow.core.common.Variable;
import com.simafei.flow.core.data.AggNode;
import com.simafei.flow.core.data.AggSpec;
import com.simafei.flow.core.data.DataManager;
import com.simafei.flow.core.data.DataNode;
import com.simafei.flow.core.data.LoadSpec;
import com.simafei.flow.core.data.StoreNode;
import com.simafei.flow.core.data.StoreSpec;
import com.simafei.flow.core.data.ds.FlowDataSource;
import com.simafei.flow.core.data.impl.SqlDataManager;
import com.simafei.flow.core.rule.FlowRules;
import com.simafei.flow.core.rule.RuleExecutor;
import com.simafei.flow.core.rule.RuleNode;
import lombok.RequiredArgsConstructor;

import java.util.List;

/**
 * @author fengpengju
 */
@RequiredArgsConstructor
public class FlowFactory {

    private final RuleExecutor ruleExecutor;

    private final ApiExecutor apiExecutor;

    private final DataManager dataManager;

    public FlowFactory(FlowDataSource dataSource) {
        this.dataManager = new SqlDataManager(dataSource);
        this.ruleExecutor = new RuleExecutor();
        this.apiExecutor = new ApiExecutor();
    }

    /**
     * 创建节点
     * @param id 节点ID
     * @param name 节点名称
     * @param blocked 是否阻塞
     * @param nodeType 节点类型
     * @return 节点
     */
    public Node createNode(String id, String name, boolean blocked, NodeType nodeType) {
        Node node = new Node(nodeType);
        node.setId(id);
        node.setName(name);
        node.setBlocked(blocked);
        return node;
    }

    public RuleNode createRuleNode(String id, String name, FlowRules rules) {
        RuleNode node = new RuleNode();
        node.setId(id);
        node.setName(name);
        node.setBlocked(false);
        node.setRules(rules);
        node.setExecutor(ruleExecutor);
        return node;
    }

    public ApiNode createApiNode(String id, String name, Api api) {
        ApiNode node = new ApiNode();
        node.setId(id);
        node.setName(name);
        node.setBlocked(false);
        node.setExecutor(apiExecutor);
        node.setApi(api);
        return node;
    }

    public AggNode createAggNode(String id, String name, AggSpec spec) {
        AggNode node = new AggNode();
        node.setId(id);
        node.setName(name);
        node.setBlocked(false);
        node.setDataManager(dataManager);
        node.setAggSpec(spec);
        return node;
    }

    public DataNode createDataNode(String id, String name, LoadSpec spec) {
        DataNode node = new DataNode();
        node.setId(id);
        node.setName(name);
        node.setBlocked(false);
        node.setDataManager(dataManager);
        node.setLoadSpec(spec);
        return node;
    }

    public StoreNode createStoreNode(String id, String name, StoreSpec spec) {
        StoreNode node = new StoreNode();
        node.setId(id);
        node.setName(name);
        node.setBlocked(false);
        node.setDataManager(dataManager);
        node.setStoreSpec(spec);
        return node;
    }

    public EndNode createEndNode(String id, String name, List<Variable> outputs) {
        EndNode node = new EndNode();
        node.setId(id);
        node.setName(name);
        node.setBlocked(false);
        node.setOutVars(outputs);
        return node;
    }

    public Node createStartNode(String id, String name) {
        return createNode(id, name, false, NodeType.START);
    }

    public Node createManualNode(String id, String name) {
        ManualNode node = new ManualNode();
        node.setId(id);
        node.setName(name);
        node.setBlocked(false);
        return node;
    }
}
